import { Base64 } from 'js-base64'

class utils {
  public getType(obj) {
    const type: any = (Object.prototype.toString.call(obj) as any)
      .match(/^\[object (.*)\]$/)[1]
      .toLowerCase()
    if (type === 'string' && typeof obj === 'object') return 'object' // Let "new String('')" return 'object'
    if (obj === null) return 'null' // PhantomJS has type "DOMWindow" for null
    if (obj === undefined) return 'undefined' // PhantomJS has type "DOMWindow" for undefined
    return type
  }

  public isEmpty(v: any): boolean {
    if (this.getType(v) === 'map') {
      return false
    }
    switch (typeof v) {
      case 'undefined':
        return true
      case 'string':
        if (v.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true
        break
      case 'boolean':
        if (!v) return true
        break
      case 'number':
        if (0 === v || isNaN(v)) return true
        break
      case 'object':
        if (null === v || v.length === 0) return true
        for (const i in v) {
          return false
        }
        return true
    }
    return false
  }

  deepClone(o: any) {
    // 判断如果不是引用类型，直接返回数据即可
    if (
      typeof o === 'string' ||
      typeof o === 'number' ||
      typeof o === 'boolean' ||
      typeof o === 'undefined'
    ) {
      return o
    } else if (Array.isArray(o)) {
      // 如果是数组，则定义一个新数组，完成复制后返回
      // 注意，这里判断数组不能用typeof，因为typeof Array 返回的是object
      // --> object
      const _arr: any = []
      o.forEach((item) => {
        _arr.push(item)
      })
      return _arr
    } else if (typeof o === 'object') {
      const _o: any = {}
      for (const key in o) {
        _o[key] = this.deepClone(o[key])
      }
      return _o
    }
  }

  /**
   * @param  {arr} 数组
   * @param  {type} 1：从小到大   2：从大到小   3：随机
   * @return {Array}
   */
  sort(arr: any, type = 1) {
    return arr.sort((a: any, b: any) => {
      switch (type) {
        case 1:
          return a - b
        case 2:
          return b - a
        case 3:
          return Math.random() - 0.5
        default:
          return arr
      }
    })
  }

  arrString(arr, prop) {
    if (arr instanceof Array && arr.length > 0) {
      let str = ''
      arr.map((item) => {
        if (prop) {
          str += item[prop] + ','
        } else {
          str += item + ','
        }
      })
      str = str.substr(0, str.length - 1)
      return str
    } else {
      return ''
    }
  }

  fzDeepClone(target) {
    // 定义一个变量
    let result
    // 如果当前需要深拷贝的是一个对象的话
    if (typeof target === 'object') {
      // 如果是一个数组的话
      if (Array.isArray(target)) {
        result = [] // 将result赋值为一个数组，并且执行遍历
        for (const i in target) {
          // 递归克隆数组中的每一项
          result.push(this.fzDeepClone(target[i]))
        }
        // 判断如果当前的值是null的话；直接赋值为null
      } else if (target === null) {
        result = null
        // 判断如果当前的值是一个RegExp对象的话，直接赋值
      } else if (target.constructor === RegExp) {
        result = target
      } else {
        // 否则是普通对象，直接for in循环，递归赋值对象的所有值
        result = {}
        for (const i in target) {
          result[i] = this.fzDeepClone(target[i])
        }
      }
      // 如果不是对象的话，就是基本数据类型，那么直接赋值
    } else {
      result = target
    }
    // 返回最终结果
    return result
  }

  datetimeToString(d: Date) {
    const year = d.getFullYear() //得到年份
    const month = d.getMonth() + 1 //得到月份
    const date = d.getDate() //得到日期
    // let day = d.getDay();//得到周几
    const hour = d.getHours() //得到小时
    const minu = d.getMinutes() //得到分钟
    const sec = d.getSeconds() //得到秒

    let monthStr = ''
    let dateStr = ''
    let hourStr = ''
    let minuStr = ''
    if (month < 10) monthStr = '0' + month
    if (date < 10) dateStr = '0' + date
    if (hour < 10) hourStr = '0' + hour
    if (minu < 10) minuStr = '0' + minu

    let time: string = year + ''
    time += '-' + month
    time += '-' + date
    time += ' ' + hour
    time += ':' + minu
    return time
  }
  dateToString(d: Date) {
    const year = d.getFullYear() //得到年份
    const month = d.getMonth() + 1 //得到月份
    const date = d.getDate() //得到日期

    let monthStr = ''
    let dateStr = ''
    if (month < 10) monthStr = '0' + month
    if (date < 10) dateStr = '0' + date

    let time: string = year + ''
    time += '-' + month
    time += '-' + date
    return time
  }
  /**
   * 获得当前时间的字符串。
   */
  getNowTimeString(): string {
    return this.datetimeToString(new Date())
  }
  getNowString(): string {
    return this.dateToString(new Date())
  }

  /**
   * 解压Base64数据。
   * @param str
   * @returns
   */
  decodeBase64(str: string): string {
    return Base64.decode(str)
  }
  /**
   * 压缩成Base64.
   * @param str
   * @returns
   */
  encodeBase64(str: string): string {
    return Base64.encode(str)
  }

  //? 传入参数名，获取值（用于已知参数名的情况）
  getQueryString(name) {
    const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
    const r = decodeURI(window.location.search.substr(1)).match(reg)
    if (r != null) {
      return unescape(r[2])
    }
    return ''
  }

  //? 获取当前url携带的所有参数集合（用于已知/未知参数名的情况）
  getAllParam() {
    const url = location.search //获取url中"?"符后的字串
    const theRequest = new Object()
    if (url.indexOf('?') != -1) {
      const str = url.substr(1)
      const strs = str.split('&')
      for (let i = 0; i < strs.length; i++) {
        theRequest[strs[i].split('=')[0]] = unescape(strs[i].split('=')[1])
      }
    }
    return theRequest
  }

  //? 获取非当前URL下面的已知参数  uri为传入的url
  getQueryStringForUrl(uri, name) {
    if (uri.indexOf('?') === -1) return ''
    uri = uri.split('?')[1]
    const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
    const r = uri.match(reg)
    if (r != null) {
      return unescape(r[2])
    }
    return null
  }

  /**
   * @description: 获取类型
   * @param {*} value
   * @return {*} string
   */
  getTypeComplete(value) {
    return (Object.prototype.toString.call(value) as any) // [object Undefined]
      .match(/\s+(\w+)/)[1] // Undefined
      .toLowerCase() // undefined
  }

  /**
   * @description: 是否为空,空数组空map空set皆为true
   * @param {*} v
   * @return {*} boolean
   */
  isEmptyComplete(v) {
    switch (this.getTypeComplete(v)) {
      case 'null':
      case 'undefined':
        return true
      case 'string':
        if (v.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true
        break
      case 'boolean':
        if (!v) return true
        break
      case 'number':
        if (0 === v || isNaN(v)) return true
        break
      case 'object':
        for (const i in v) {
          return false
        }
        return true
      case 'map':
        if (v.size === 0) {
          return true
        }
        return false
      case 'array':
        if (v.length === 0) {
          return true
        }
        return false
      case 'set':
        if (v.size === 0) {
          return true
        }
        return false
    }
    return false
  }

  /**
   * @description: 判断对象的属性是否为空
   * @param {*} obj
   * @param {*} prop
   * @return {*}
   */
  objPropIsEmpty(obj, prop) {
    // eslint-disable-next-line no-prototype-builtins
    if (!obj.hasOwnProperty(prop)) {
      return true
    }
    return this.isEmptyComplete(obj[prop])
  }

  /**
   * @description: 防抖
   * @param {*} func 要执行的函数
   * @param {*} delay  延迟时间
   * @return {*}
   */
  debounce(func, delay) {
    let timer: any = null
    return function () {
      if (timer) {
        clearTimeout(timer)
        timer = null
      }
      timer = setTimeout(() => {
        func(...arguments)
      }, delay)
    }
  }
  isNull(v: any): boolean {
    if (v === null || v === undefined) {
      return true
    }
    return false
  }
  /**
   * 是否是方法。
   * @param obj
   * @returns
   */
  isFunction(obj: any) {
    if (!this.isEmpty(obj)) {
      try {
        return typeof obj === 'function'
      } catch (e) {
        console.log(e)
      }
    }
    return false
  }

  //  判断是否为移动端
  isMobile() {
    let isMobile = false
    if (
      navigator.userAgent.match(
        /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
      )
    ) {
      // console.log('移动端');
      isMobile = true
    }
    if (document.body.clientWidth < 800) {
      isMobile = true
    }
    return isMobile
  }
}
export default new utils() //用的是export default方法，并且导出的时候就已经实例化了
